package compute

import (
	"gitee.com/amoyx/cloud-provider/pkg/cloud/tencent/models"
	qcbs "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs/v20170312"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
)

type CbsGreeter interface {
	CBS(zone string) CbsInterface
}

type CbsInterface interface {
	Create(in models.CbsRequest) (ids []string, err error)
	Get(id string) (result models.CbsResponse, err error)
	Update()
	Delete(id string) (requestId string, err error)
	QueryPrepaidPrice(in models.CbsRequest) (result models.ItemPrice, err error)
	ResizeDisk(id string, size uint64) (requestId string, err error)
	DetachDisk(cvmId string, diskId string) bool
	ListByName(name string) (list []models.CbsResponse, err error)
	List() (list []models.CbsResponse, err error)
}

type cbs struct {
	region  string
	compute *Compute
	client  *qcbs.Client
}

func newCbs(compute *Compute, region string) CbsInterface {
	c := &cbs{
		compute: compute,
		region:  region,
	}
	cpf := profile.NewClientProfile()
	cpf.HttpProfile.Endpoint = string(CbsEndPoint)
	client, _ := qcbs.NewClient(c.compute.Credential(), c.region, cpf)
	c.client = client
	return c
}

func (c *cbs) Create(in models.CbsRequest) (ids []string, err error) {
	request := qcbs.NewCreateDisksRequest()
	request.DiskName = common.StringPtr(in.DiskName)
	request.DiskChargeType = common.StringPtr(in.DiskChargeType)
	request.DiskCount = common.Uint64Ptr(in.DiskCount)
	request.DiskType = common.StringPtr(in.DiskType)
	request.DiskSize = common.Uint64Ptr(in.DiskSize)
	if in.DiskChargeType == string(models.PREPAID) {
		request.DiskChargePrepaid = &qcbs.DiskChargePrepaid{
			RenewFlag: common.StringPtr(in.DiskRenewFlag),
			Period:    common.Uint64Ptr(in.Period),
		}
	}
	response, err := c.client.CreateDisks(request)
	if err != nil {
		return
	}
	for _, val := range response.Response.DiskIdSet {
		ids = append(ids, *val)
	}
	return ids, nil
}

func (c *cbs) Get(id string) (result models.CbsResponse, err error) {
	list, err := c.query(map[string]string{"disk-id": id})
	if len(list) > 0 {
		result = list[0]
	}
	return
}

func (c *cbs) ListByName(name string) (list []models.CbsResponse, err error) {
	list, err = c.query(map[string]string{"disk-name": name})
	return
}

func (c *cbs) Update() {

}

// QueryPrepaidPrice 查询预付费价格
func (c *cbs) QueryPrepaidPrice(in models.CbsRequest) (result models.ItemPrice, err error) {
	request := qcbs.NewInquiryPriceCreateDisksRequest()
	request.DiskChargeType = common.StringPtr("PREPAID")
	request.DiskCount = common.Uint64Ptr(in.DiskCount)
	request.DiskType = common.StringPtr(in.DiskType)
	request.DiskSize = common.Uint64Ptr(in.DiskSize)
	period := in.Period
	if period < 1 {
		period = 1
	}
	request.DiskChargePrepaid = &qcbs.DiskChargePrepaid{
		Period: common.Uint64Ptr(period),
	}
	response, err := c.client.InquiryPriceCreateDisks(request)
	if err != nil {
		return
	}
	price := response.Response.DiskPrice
	result = models.ItemPrice{
		DiscountPrice: *price.DiscountPrice,
		OriginalPrice: *price.OriginalPrice,
	}
	return
}

// QueryPostpaidPrice 查询后付费价格
func (c *cbs) QueryPostpaidPrice(in models.CbsRequest) (result models.ItemPrice, err error) {
	request := qcbs.NewInquiryPriceCreateDisksRequest()
	request.DiskChargeType = common.StringPtr("POSTPAID_BY_HOUR")
	request.DiskCount = common.Uint64Ptr(in.DiskCount)
	request.DiskType = common.StringPtr(in.DiskType)
	request.DiskSize = common.Uint64Ptr(in.DiskSize)
	response, err := c.client.InquiryPriceCreateDisks(request)
	if err != nil {
		return
	}
	price := response.Response.DiskPrice
	result = models.ItemPrice{
		UnitPrice:         *price.UnitPrice,
		UnitPriceDiscount: *price.UnitPriceDiscount,
	}
	return
}

// ResizeDisk 磁盘扩容
func (c *cbs) ResizeDisk(id string, size uint64) (requestId string, err error) {
	request := qcbs.NewResizeDiskRequest()
	request.DiskId = common.StringPtr(id)
	request.DiskSize = common.Uint64Ptr(size)
	response, err := c.client.ResizeDisk(request)
	return *response.Response.RequestId, err
}

// Delete 退还云硬盘
func (c *cbs) Delete(id string) (requestId string, err error) {
	request := qcbs.NewTerminateDisksRequest()
	request.DiskIds = common.StringPtrs([]string{id})
	response, err := c.client.TerminateDisks(request)
	return *response.Response.RequestId, err
}

// DetachDisk 卸载云盘
func (c *cbs) DetachDisk(cvmId string, diskId string) bool {
	request := qcbs.NewDetachDisksRequest()
	request.InstanceId = common.StringPtr(cvmId)
	request.DiskIds = common.StringPtrs([]string{diskId})
	_, err := c.client.DetachDisks(request)
	if err != nil {
		return false
	}
	return true
}

func (c *cbs) List() (list []models.CbsResponse, err error) {
	return c.query(map[string]string{})
}

func (c *cbs) query(args map[string]string) (list []models.CbsResponse, err error) {
	request := qcbs.NewDescribeDisksRequest()
	var filters []*qcbs.Filter
	for key, val := range args {
		filters = append(filters, &qcbs.Filter{
			Name:   common.StringPtr(key),
			Values: common.StringPtrs([]string{val}),
		})
	}
	request.Filters = filters
	request.Limit = common.Uint64Ptr(100)
	request.Offset = common.Uint64Ptr(0)
	request.Order = common.StringPtr("ASC")
	response, err := c.client.DescribeDisks(request)
	for _, row := range response.Response.DiskSet {
		list = append(list, models.CbsResponse{
			RenewFlag:      *row.RenewFlag,
			DiskType:       *row.DiskType,
			DiskState:      *row.DiskState,
			DiskName:       *row.DiskName,
			InstanceId:     *row.InstanceId,
			DiskId:         *row.DiskId,
			DeadlineTime:   *row.DeadlineTime,
			Attached:       *row.Attached,
			DiskSize:       *row.DiskSize,
			DiskUsage:      *row.DiskUsage,
			DiskChargeType: *row.DiskChargeType,
			CreateTime:     *row.CreateTime,
		})
	}
	return
}
